<?php

namespace App\Kuafu\Coupon\Validate;

use App\Exceptions\CustomValidateException;
use App\Http\Validate\AbstractBaseValidate;
use App\Kuafu\Base\Util\DateTimeUtil;
use App\Kuafu\Coupon\Enum\CouponCodeEnum;
use App\Kuafu\Coupon\Enum\CouponEnum;
use App\Kuafu\Coupon\Exceptions\CouponException;
use Illuminate\Support\MessageBag;
use Illuminate\Validation\Rule;
use Illuminate\Validation\ValidationException;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;

class CouponNewValidate extends AbstractBaseValidate
{
    /**
     * @inheritDoc
     */
    function getRules(): array
    {
        // TODO: Implement getRules() method.
        return [
            'type'                => 'required|int|in:' . implode(',', array_keys(CouponEnum::COUPONTYPE)),
            'name'                => 'required|string|min:1|max:50',
            'useTimeType'         => 'required|int|in:' . implode(',', array_keys(CouponEnum::TIME_TYPES)),
            'discount'            => 'required|int|min:0',
            'startAt'             => 'required',
            'endAt'               => 'required',
            'useCondition'        => 'required|int|min:0',
            'availableSource'     => 'required|string', // 0,3,2,4
            'isSuperposeCoupon'   => 'required_if:type,' . CouponEnum::COUPON_TYPE_VOUCHERS . ',' . CouponEnum::COUPON_TYPE_DISCOUNT . '|int|in:0,1',
            'isSuperposeActivity' => 'required_if:type,' . CouponEnum::COUPON_TYPE_VOUCHERS . ',' . CouponEnum::COUPON_TYPE_DISCOUNT . '|int|in:0,1',
            'unableDate'          => 'sometimes|string', // 1,3,4,8
            'unableTime'          => 'sometimes|array',
            'canUseProduct'       => 'exclude_unless:type,' . CouponEnum::COUPON_TYPE_EXCHANGE . '|int|min:1',
            'couponImg'           => 'required_if:type,' . CouponEnum::COUPON_TYPE_EXCHANGE . '|string|min:1|max:255',
            "cappedAmount"        => "sometimes|int|min:0",
            "isExpireNotice"      => "required|int|in:0,1",
            "isArrivalNotice"     => "required|int|in:0,1",
            "expireNoticeDay"     => "required_if:isExpireNotice,1|int|min:0"
        ];
    }

    /**
     * @inheritDoc
     */
    function getAttributes(): array
    {
        // TODO: Implement getAttributes() method.
        return [];
    }

    /**
     * @inheritDoc
     */
    function registerValidateRules(): void
    {
        // TODO: Implement registerValidateRules() method.
    }

    /**
     * @inheritDoc
     */
    function getMessages(): array
    {
        // TODO: Implement getMessages() method.
        return [];
    }


    /**
     * @param array $params
     * @return MessageBag|object
     * @throws CustomValidateException
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     */
    public static function updateValidate(array $params)
    {
        return self::getInstance()->validate(
            [
                "id",
                'useTimeType',
                'startAt',
                'endAt',
                'availableSource',
                'isSuperposeCoupon',
                'isSuperposeActivity',
                'unableDate',
                'unableTime',
                'couponImg',
                "desc",
                "cappedAmount",
                "isExpireNotice",
                "isArrivalNotice",
                "expireNoticeDay"
            ],
            $params,
            [
                "id"                => Rule::exists("coupons")->where("status", CouponEnum::STATUS_DISABLE),
                "desc"              => self::stringValidateBuild(false, 400),
                "unableDate"        => "sometimes|array",
                "unableDate.*"      => "int|min:1|max:8",
                "availableSource"   => "required|array",
                "availableSource.*" => "int|min:0",
            ],
            true,
            function (array $params) {
                switch ($params["useTimeType"]) {
                    case CouponEnum::TIME_TYPE_ABSOLUTE:
                        $params["startAt"] = strtotime($params['startAt']);
                        $params["endAt"]   = strtotime($params['endAt']);
                        break;
                    case CouponEnum::TIME_TYPE_RELATIVE:
                        // 领取后第$data['startAt']天后可以使用，有效$data['endAt']天数
                        if ($params['startAt'] < 0) {
                            throw new CouponException(CouponCodeEnum::ERR_COUPON_PARAM_VALID, '有效期开始天数至少为0天');
                        }
                        if ($params['endAt'] < 1) {
                            throw new CouponException(CouponCodeEnum::ERR_COUPON_PARAM_VALID, '有效期有线天数至少为1天');
                        }
                        $params["startAt"] = $params['startAt'];
                        $params["endAt"]   = $params['endAt'];
                        break;
                }
                $params["availableSource"] = array_sum($params["availableSource"]);
                $params["unableDate"]      = collect($params["unableDate"])->implode(",");

                foreach ($params['unableTime'] as &$item) {
                    if (!isset($item['startAt']) || !isset($item['endAt'])) {
                        throw new CouponException(CouponCodeEnum::ERR_COUPON_PARAM_VALID, '不可用时间格式不正确');
                    }
                    $item['startAt'] = DateTimeUtil::clockToSeconds($item['startAt']);
                    $item['endAt']   = DateTimeUtil::clockToSeconds($item['endAt']);
                    if (null === $item['startAt'] || $item['startAt'] < 0) {
                        throw new CouponException(CouponCodeEnum::ERR_COUPON_PARAM_VALID, '不可用时间不能早于00:00');
                    }
                    if (null === $item['endAt'] || $item['endAt'] >= 86400) {
                        throw new CouponException(CouponCodeEnum::ERR_COUPON_PARAM_VALID, '不可用时间不能晚于23:59');
                    }
                    if ($item['startAt'] > $item['endAt']) {
                        throw new CouponException(CouponCodeEnum::ERR_COUPON_PARAM_VALID, '不可用时间起始时间不能晚于结束时间');
                    }
                }
                $params["unableTime"] = json_encode($params['unableTime']);
                if (isset($params["couponImg"])) {
                    $params["couponImg"] = getPicturePath($params["couponImg"]);
                }
                return $params;
            }
        );
    }
}
